/* eslint-disable complexity */
import * as Util from './util'
/**
 * Creates a XHR request
 * @param {Object} options
 * @return {XMLHttpRequest}
 */
const createRequest = (options) => {
  const xhr = new XMLHttpRequest()
  xhr.open(options.method || 'GET', options.url, true)
  xhr.responseType = options.responseType || 'json'
  if (options.header) {
    Object.keys(options.header).forEach(key => {
      xhr.setRequestHeader(key, options.header[key])
    })
  }
  xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
  return xhr
}

/**
 * Send a XHR request
 * @param {XMLHttpRequest} xhr
 * @return {Promise}
 */
const sendRequest = (xhr, data) => {
  const promise = new Promise((resolve, reject) => {
    xhr.onload = () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        const response = {statusCode: xhr.status, data: {}}
        try {
          response.data = JSON.parse(xhr.response)
        } catch (err) {
          response.data = xhr.response
        }
        resolve(response)
      } else {
        // eslint-disable-next-line prefer-promise-reject-errors
        reject({statusCode: xhr.status, errMsg: xhr.response})
      }
    }
    xhr.onerror = (err) => reject(err)
    // eslint-disable-next-line prefer-promise-reject-errors
    xhr.onabort = () => reject('abort')
    xhr.send(data)
  })

  promise.abort = () => {
    xhr.abort()
  }
  return promise
}

/**
 * Send a normal request
 * @param {Object} options
 * @returns Promise
 */
export default function (options) {
  options = Util.extend({}, options)
  options.method = (options.method || 'GET').toUpperCase()
  let data
  if (options.data) {
    data = ''
    Object.keys(options.data).forEach(key => {
      if (options.data[key] === undefined) return
      if (data) data += '&'
      data += `${key}=${options.data[key]}`
    })
  }
  if (options.method === 'GET' && data) {
    options.url += `?${data}`
    data = null
  }
  if (options.method === 'POST') {
    const header = options.header || {}
    if (options.dataType === 'json') {
      header['content-type'] = header['content-type'] || 'application/json;charset=utf-8'
      data = JSON.stringify(options.data)
    } else if (data) {
      header['content-type'] = header['content-type'] || 'application/x-www-form-urlencoded;charset=utf-8'
    }
    options.header = header
  }
  return sendRequest(createRequest(options), data)
}
